#!/usr/bin/env python

import wx
import sys

def read_text_from(file_path):
    " Reads all the text from a file and returns it as a string. "
    f = open(file_path, 'r')
    lyrics = f.read()
    f.close()
    return lyrics

class LyricsView(wx.Control):
    def __init__(self, parent):
        wx.Control.__init__(self, parent)

        for event, handler in \
            [(wx.EVT_KEY_DOWN, self.on_key_down),
             (wx.EVT_KEY_UP, self.on_key_up),
             (wx.EVT_CHAR, self.on_key_char),
             (wx.EVT_LEFT_DOWN, self.on_mouse_left_down),
             (wx.EVT_LEFT_UP, self.on_mouse_left_up),
             (wx.EVT_MOTION, self.on_mouse_motion),
             (wx.EVT_PAINT, self.on_paint),
             (wx.EVT_SIZE, self.on_resize)]:
            self.Bind(event, handler)

        self.focused_segment = 0

    def set_lyrics(self, lyrics):
        self.lyrics = lyrics

    def on_key_down(self, e):
        key_code = e.GetKeyCode()
        shift_down = e.ShiftDown()
        control_down = e.ControlDown()

        if key_code == wx.WXK_LEFT:
            if shift_down:
                segments = self.get_segments()

                if self.focused_segment < len(segments) and \
                    self.focused_segment > 0:
                    previous_segment = self.focused_segment-1
                    if len(segments[previous_segment]) > 0:
                        segments[self.focused_segment] = segments[previous_segment][len(segments[previous_segment])-1] + segments[self.focused_segment]
                        segments[previous_segment] = segments[previous_segment][:-1]

                        # remove empty segments
                        def is_empty(string):
                            return len(string) <= 0
                        for segment in filter(is_empty, segments):
                            segments.remove(segment)
                            self.focused_segment -= 1

                        self.lyrics = "|".join(segments)
                        self.repaint()
            else:
                if self.focused_segment > 0:
                    self.focused_segment -= 1
                    self.repaint()
        elif key_code == wx.WXK_RIGHT:
            if shift_down:
                segments = self.get_segments()

                if self.focused_segment < len(segments) and \
                    self.focused_segment >= 0:
                    next_segment = self.focused_segment+1
                    if len(segments[next_segment]) > 0:
                        segments[self.focused_segment] += segments[next_segment][0]
                        segments[next_segment] = segments[next_segment][1:]

                        # remove empty segments
                        def is_empty(string):
                            return len(string) <= 0
                        for segment in filter(is_empty, segments):
                            segments.remove(segment)

                        self.lyrics = "|".join(segments)
                        self.repaint()
            else:
                self.focused_segment += 1
                self.repaint()
        else:
            e.Skip()

    def on_key_up(self, e):
        e.Skip()

    def on_key_char(self, e):
        e.Skip()

    def on_mouse_left_down(self, e):
        e.Skip()

    def on_mouse_left_up(self, e):
        e.Skip()

    def on_mouse_motion(self, e):
        e.Skip()

    def on_resize(self, e):
        e.Skip()

    def on_paint(self, e):
        dc = wx.BufferedPaintDC(self)
        dc.Clear()

        segments = self.get_segments()

        x = 0
        y = 30
        index = 0

        for segment in segments:
            if index == self.focused_segment:
                dc.SetBrush(wx.GREY_BRUSH)
            else:
                dc.SetBrush(wx.WHITE_BRUSH)

            text_width, text_height = dc.GetTextExtent(segment)
            dc.DrawRoundedRectangle(x, y, text_width, text_height, 5)
            dc.DrawText(segment, x, y)
            x += text_width
            index += 1

    def repaint(self):
        self.Refresh(False)

    def get_segments(self):
        return self.lyrics.split("|")

class MainWindow(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, wx.ID_ANY, title, size=(640, 480))

        self.control = LyricsView(self)

        self.Show(True)

def main():
    if len(sys.argv) != 2:
        print "Usage: words [lyrics_file]"
        sys.exit()

    try:
        lyrics = read_text_from(sys.argv[1])
    except IOError:
        print "words: " + sys.argv[1] + ": No such file or directory"
        sys.exit()

    app = wx.PySimpleApp()
    frame = MainWindow(None, -1, 'Words')
    frame.control.set_lyrics(lyrics)
    app.MainLoop()

if __name__ == '__main__':
    main()
